﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using CodePlex.WebServices.Client;
using Microsoft.Win32;

namespace VSCPPublishPlugin.Ui
{
	public partial class ProfileConfigForm : Form
	{
		public ProfileConfigForm()
		{
			InitializeComponent();
		}

		private ProfileSettings _loadedProfileSettings;
		private ProfileSettings _currentProfileSettings;
		private const string SettingsKey = "Software\\Double A Software\\CodePlexAddin\\CPA10";

		private void LoadSettings(bool selectFirst = true)
		{
			cboProfiles.Items.Clear();
			var profileNames = GetAllProfileNames();
			foreach (var profile in profileNames)
			{
				cboProfiles.Items.Add(profile);
			}

			if (selectFirst)
				cboProfiles.SelectedIndex = 0;
		}

		private static void SaveSettings(ProfileSettings profile)
		{
			var key = Registry.CurrentUser.OpenSubKey(SettingsKey, true);
			if (null == key)
			{
				key = Registry.CurrentUser.CreateSubKey(SettingsKey);
			}
			var settKey = key.OpenSubKey(profile.ProfileName, true);
			if (null == settKey)
			{
				settKey = key.CreateSubKey(profile.ProfileName);
			}
			settKey.SetValue("Username", profile.Username);
			settKey.SetValue("Password", profile.Password);
			settKey.SetValue("ProjectName", profile.ProjectName);
			settKey.SetValue("ProjectUrl", profile.CodePlexUrl);

			// release settings
			settKey.SetValue("ReleaseName", profile.ReleaseName);
			settKey.SetValue("ReleaseDescription", profile.ReleaseDescription);
			settKey.SetValue("ReleaseDate", (profile.ReleaseDate.HasValue ? profile.ReleaseDate.Value.ToBinary() : -1).ToString());
			settKey.SetValue("ReleaseIsDefault", profile.IsDefaultRelease.ToString());
			settKey.SetValue("ReleaseChangesetId", profile.ChangesetId);
			settKey.SetValue("ReleaseStatus", profile.ReleaseStatus.ToString());
			settKey.SetValue("ReleaseReplaceIfExists", profile.ReplaceIfExists.ToString());

			// publish settings
			settKey.SetValue("OpenReleasePageOnPublish", profile.OpenReleasePageOnPublish.ToString());


			settKey.Close();
			key.Close();
		}
		private static ProfileSettings LoadProfile(string profileName)
		{
			var profile = new ProfileSettings();

			var key = Registry.CurrentUser.OpenSubKey(SettingsKey);
			if (null == key)
			{
				profile = ProfileSettings.Empty;
				profile.ProfileName = profileName;

				//CopySettingsToForm(_loadedProfileSettings);
				return profile;
			}

			key = key.OpenSubKey(profileName);
			if (null != key)
			{
				profile.ProfileName = profileName;
				profile.Username = (string)key.GetValue("Username", "");
				profile.Password = (string)key.GetValue("Password", "");
				profile.ProjectName = (string)key.GetValue("ProjectName", "");
				profile.CodePlexUrl = (string)key.GetValue("ProjectUrl", "");

				// release settings
				profile.ReleaseName = (string)key.GetValue("ReleaseName", "");
				profile.ReleaseDescription = (string)key.GetValue("ReleaseDescription", "");
				{
					var tmp = (string)key.GetValue("ReleaseDate", "");
					long lng;
					DateTime? relDate;
					if (string.IsNullOrEmpty(tmp) || !long.TryParse(tmp, out lng) || lng < 0)
						relDate = null;
					else
						relDate = DateTime.FromBinary(lng);
					profile.ReleaseDate = relDate;
				}
				{
					var tmp = (string)key.GetValue("ReleaseIsDefault", "");
					bool b;
					if (!bool.TryParse(tmp, out b))
						b = false;
					profile.IsDefaultRelease = b;
				}
				profile.ChangesetId = (string)key.GetValue("ReleaseChangesetId", "");
				{
					var tmp =(string)key.GetValue("ReleaseStatus", "");
					ReleaseStatus rstatus;
					if (!Enum.TryParse(tmp, true, out rstatus))
						rstatus = ReleaseStatus.Planning;
					profile.ReleaseStatus = rstatus;
				}
				{
					var tmp = (string)key.GetValue("ReleaseReplaceIfExists", "");
					bool b;
					if (!bool.TryParse(tmp, out b))
						b = false;
					profile.ReplaceIfExists = b;
				}

				// publish options
				{
					var tmp = (string)key.GetValue("OpenReleasePageOnPublish", "");
					bool b;
					if (!bool.TryParse(tmp, out b))
						b = false;
					profile.OpenReleasePageOnPublish = b;
				}

				key.Close();
			}
			else
			{
				profile = ProfileSettings.Empty;
				profile.ProfileName = profileName;
			}

			//CopySettingsToForm(_loadedProfileSettings);
			return profile;
		}

		private void DeleteProfile(string profileName)
		{
			if (string.IsNullOrEmpty(profileName))
				return;

			var key = Registry.CurrentUser.OpenSubKey(SettingsKey, true);
			if (null == key)
			{
				return;
			}

			key.DeleteSubKeyTree(profileName, false);
			key.Close();
		}

		private void CopySettingsToForm(ProfileSettings profileSettings)
		{
			txtUsername.Text = profileSettings.Username;
			txtPassword.Text = profileSettings.Password;
			txtProjectName.Text = profileSettings.ProjectName;
			txtProjectUrl.Text = profileSettings.CodePlexUrl;

			// release settings
			txtReleaseName.Text = profileSettings.ReleaseName;
			txtReleaseDescription.Text = profileSettings.ReleaseDescription;
			DateTime relDate;
			if (profileSettings.ReleaseDate.HasValue)
			{
				if (profileSettings.ReleaseDate.Value < dtpReleaseDate.MinDate || profileSettings.ReleaseDate.Value > dtpReleaseDate.MaxDate)
					relDate = DateTime.Today;
				else
					relDate = profileSettings.ReleaseDate.Value;
			}
			else
				relDate = DateTime.Today;
			dtpReleaseDate.Value = relDate;
			chkIsDefault.Checked = profileSettings.IsDefaultRelease;
			txtChangesetId.Text = profileSettings.ChangesetId;
			cboReleaseStatus.SelectedItem = profileSettings.ReleaseStatus;
			chkReplaceReleaseIfExists.Checked = profileSettings.ReplaceIfExists;

			// publish options
			chkOpenReleasePageOnPublish.Checked = profileSettings.OpenReleasePageOnPublish;

		}

		private void GetCurrentSettings()
		{
			_currentProfileSettings.ProfileName = cboProfiles.Text;

			// project settings
			_currentProfileSettings.Username = txtUsername.Text;
			_currentProfileSettings.Password = txtPassword.Text;
			_currentProfileSettings.ProjectName = txtProjectName.Text;
			_currentProfileSettings.CodePlexUrl = txtProjectUrl.Text;

			// release settings
			_currentProfileSettings.ReleaseName = txtReleaseName.Text;
			_currentProfileSettings.ReleaseDescription = txtReleaseDescription.Text;
			_currentProfileSettings.ReleaseDate = dtpReleaseDate.Value;
			_currentProfileSettings.IsDefaultRelease = chkIsDefault.Checked;
			_currentProfileSettings.ChangesetId = txtChangesetId.Text;
			_currentProfileSettings.ReleaseStatus = (ReleaseStatus)cboReleaseStatus.SelectedItem;
			_currentProfileSettings.ReplaceIfExists = chkReplaceReleaseIfExists.Checked;

			// publish options
			_currentProfileSettings.OpenReleasePageOnPublish = chkOpenReleasePageOnPublish.Checked;
		}

		private void ClearForm()
		{
			var clear = ProfileSettings.Empty;
			CopySettingsToForm(clear);
		}


		private void btnSave_Click(object sender, EventArgs e)
		{
			GetCurrentSettings();
			SaveSettings(_currentProfileSettings);
			NeedReload = true;
		}

		private void btnPublish_Click(object sender, EventArgs e)
		{
			GetCurrentSettings();
			SaveSettings(_currentProfileSettings);
			NeedReload = true;

			SelectedProfileName = (string)cboProfiles.SelectedItem;
			this.DialogResult = DialogResult.Yes;
			this.Close();
		}

		private void btnClose_Click(object sender, EventArgs e)
		{
			SelectedProfileName = (string)cboProfiles.SelectedItem;
			this.DialogResult = DialogResult.Cancel;
			this.Close();
		}

		private void ConfigForm_Load(object sender, EventArgs e)
		{
			cboReleaseStatus.Items.Clear();
			var statuses = new[]
			               {
			               	ReleaseStatus.Planning, ReleaseStatus.Alpha, ReleaseStatus.Beta, ReleaseStatus.Stable
			               };
			cboReleaseStatus.DataSource = statuses;
			cboReleaseStatus.SelectedItem = ReleaseStatus.Planning;

			LoadSettings();
		}

		private void RefreshFormState()
		{
			if (-1 == cboProfiles.SelectedIndex)
			{
				btnDelete.Enabled = false;
				btnSave.Enabled = false;
				btnPublish.Enabled = false;

				ClearForm();
			}
			else
			{
				btnDelete.Enabled = true;
				btnSave.Enabled = true;
				btnPublish.Enabled = true;

				_loadedProfileSettings = LoadProfile((string)cboProfiles.SelectedItem);
				CopySettingsToForm(_loadedProfileSettings);
			}
		}

		private bool _isAddingNew = false;

		private void btnAddNew_Click(object sender, EventArgs e)
		{
			_isAddingNew = true;
			cboProfiles.DropDownStyle = ComboBoxStyle.DropDown;
			cboProfiles.SelectedIndex = -1;
			cboProfiles.Items.Clear();
			cboProfiles.Text = "";
			cboProfiles.Focus();

			ClearForm();
		}

		private void cboProfiles_SelectedIndexChanged(object sender, EventArgs e)
		{
			RefreshFormState();
		}

		private void cboProfiles_Leave(object sender, EventArgs e)
		{
			if (!_isAddingNew)
				return;

			SubmitAddingNew();
		}

		private void cboProfiles_KeyDown(object sender, KeyEventArgs e)
		{
			if (!_isAddingNew)
				return;

			if (e.KeyCode == Keys.Escape)
			{
				CancelAddingNew();
			}
			else if (Keys.Enter == e.KeyCode || Keys.Return == e.KeyCode)
			{
				SubmitAddingNew();
			}
		}

		private void SubmitAddingNew()
		{
			_isAddingNew = false;
			GetCurrentSettings();
			cboProfiles.DropDownStyle = ComboBoxStyle.DropDownList;
			if (!string.IsNullOrEmpty(_currentProfileSettings.ProfileName))
			{
				SaveSettings(_currentProfileSettings);
				NeedReload = true;
				var name = _currentProfileSettings.ProfileName;
				LoadSettings(false);
				cboProfiles.SelectedItem = name;

				txtUsername.Focus();
			}
			else
			{
				LoadSettings();
				cboProfiles.Focus();
			}
		}

		private void CancelAddingNew()
		{
			_isAddingNew = false;
			cboProfiles.DropDownStyle = ComboBoxStyle.DropDownList;
			LoadSettings();
			cboProfiles.Focus();
		}

		private void btnDelete_Click(object sender, EventArgs e)
		{
			DeleteProfile((string)cboProfiles.SelectedItem);
			NeedReload = true;
			var i = cboProfiles.SelectedIndex;
			cboProfiles.Items.RemoveAt(cboProfiles.SelectedIndex);
			if (cboProfiles.Items.Count == 0)
			{
				cboProfiles.SelectedIndex = -1;
				RefreshFormState();
			}
			else if (cboProfiles.Items.Count <= i)
			{
				cboProfiles.SelectedIndex = cboProfiles.Items.Count - 1;
			}
			else
			{
				cboProfiles.SelectedIndex = i;
			}
		}


		public bool NeedReload = false;
		public string SelectedProfileName = null;

		public static ProfileSettings LoadProfileSettingsByName(string profileName)
		{
			return LoadProfile(profileName);
		}
		public static string[] GetAllProfileNames()
		{
			string[] profileNames = null;
			var key = Registry.CurrentUser.OpenSubKey(SettingsKey);
			if (null != key)
			{
				// get list of all profiles
				profileNames = key.GetSubKeyNames();
				key.Close();
			}

			return profileNames;
		}
		public static IEnumerable<ProfileSettings> LoadAllProfiles()
		{
			var profileNames = GetAllProfileNames();
			foreach (var name in profileNames)
			{
				yield return LoadProfileSettingsByName(name);
			}
		}

		private void cboReleaseStatus_SelectedIndexChanged(object sender, EventArgs e)
		{
			var selectedStatus = (ReleaseStatus)cboReleaseStatus.SelectedItem;
			switch (selectedStatus)
			{
				case ReleaseStatus.Planning:
					AdditionalSettingsPanel.Enabled = false;
					break;
				case ReleaseStatus.Alpha:
				case ReleaseStatus.Beta:
				case ReleaseStatus.Stable:
					AdditionalSettingsPanel.Enabled = true;
					break;
			}
		}
	}

	public struct ProfileSettings
	{
		public static ProfileSettings Empty = new ProfileSettings()
		{
			ProfileName = "",
			Username = "",
			Password = "",
			ProjectName = "",
			CodePlexUrl = "",

			ReleaseName = "",
			ReleaseDescription = "",
			ReleaseDate = null,
			IsDefaultRelease = false,
			ChangesetId = "",
			ReleaseStatus = ReleaseStatus.Planning,
			OpenReleasePageOnPublish = false,
			ReplaceIfExists = true,
		};

		public string ProfileName;
		public string Username;
		public string Password;
		public string ProjectName;
		public string CodePlexUrl;
		public string ReleaseName;
		public string ReleaseDescription;
		public DateTime? ReleaseDate;
		public ReleaseStatus ReleaseStatus;
		public bool IsDefaultRelease;
		public string ChangesetId;
		public bool OpenReleasePageOnPublish;
		public bool ReplaceIfExists;
	}
}
